<?php

namespace App\Http\Services;

use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use App\Http\Model\Hint;
use App\Http\Model\Gift;
use App\Http\Model\User;
use App\Http\Model\FinanceUserWallet;
use App\Http\Model\FinanceDiamond;
use App\Http\Model\FinanceEnergy;
use App\Http\Model\FinanceEnergyCoin;
use App\Http\Model\GiftBag;
use App\Http\Model\Mall;
use App\Http\Model\Angerbird;
use App\Http\Model\System;
use App\Http\Services\MsgServices;
use App\Http\Services\RoomMsgServices;

class AngerbirdServices extends CommonServices
{
    protected $giftModel;
    protected $userModel;
    protected $userWalletModel;
    protected $financeDiamondModel;
    protected $financeEnergyModel;
    protected $financeEnergyCoinModel;
    protected $giftBag_model;
    protected $mallModel;
    protected $angerbirdModel;
    protected $msgService;
    protected $roomMsgService;
    protected $model_system;

    protected $logName = 'angerbird';//日志名
    protected $errorLogName = 'error_angerbird';//日志名
    //游戏房间ID
    protected $gameRoomId = 107;
    //倒计时持续时间
    protected $countdownNum = 10;
    //最高高度
    protected $maxHeight = 9900;
    //奖励高度起始
    protected $rewardHeight = 110;

    //缓存有效期
    protected $cacheExpire = 172800;
    //脚本执行锁
    protected $activityPromotionLockKey = 'ANGERBIRD:PROMOTION:LOCK:';//sring ANGERBIRD:PROMOTION:LOCK:{type}:{类型}

    //当前游戏局数
    protected $gameNumKey = 'ANGERBIRD:GAME:NUM';//string ANGERBIRD:GAME:NUM => {num}
    //利润池
    protected $profitTotalKey = 'ANGERBIRD:PROFITTOTAL';//string ANGERBIRD:PROFITTOTAL => {num}
    //押注池 能量 等于1分
    protected $trackPoolTotalKey = 'ANGERBIRD:TRACKPOOL:TOTAL';//string ANGERBIRD:TRACKPOOL:TOTAL => {num}
    //某局所有用户押注信息
    protected $userStakeKey = 'ANGERBIRD:USERSTAKE:';//hsah ANGERBIRD:USERSTAKE:{gameNum} => {user_id}=>{height,energy_num}
    //某局押注的所有用户根据时间排序
    protected $allUserStakeKey = 'ANGERBIRD:AllUSERSTAKE:';//zset ANGERBIRD:AllUSERSTAKE:{gameNum} => {时间戳}=>{user_id}
    //某局兑换的所有用户根据时间排序
    protected $allUserRewardKey = 'ANGERBIRD:AllUSERREWARD:';//zset ANGERBIRD:AllUSERREWARD:{gameNum} => {时间戳}=>{user_id}
    //某局已兑换的能量币总值
    protected $allEnergyCoinRewardKey = 'ANGERBIRD:ALLENERGYCOINREWARD:';//string ANGERBIRD:ALLENERGYCOINREWARD:{gameNum} => {energy_coin}
    //某局游戏阶段 1=倒计时阶段 2=起飞阶段 3=飞行阶段 4=结果展示阶段
    protected $gameStatusKey = 'ANGERBIRD:GAMESTATUS:';//string ANGERBIRD:GAMESTATUS:{gameNum} => {num}
    //某局游戏飞行高度
    protected $gameHeightKey = 'ANGERBIRD:GAMEHEIGHT:';//string ANGERBIRD:GAMEHEIGHT:{gameNum} => {num}
    //某局游戏倒计时
    protected $gameCountdownNumKey = 'ANGERBIRD:GAME:COUNTDOWNNUM';//string ANGERBIRD:GAME:COUNTDOWNNUM:{gameNum} => {num}

    public function __construct()
    {
        parent::__construct();

        $this->giftModel = new Gift();
        $this->userModel = new User();
        $this->userWalletModel = new FinanceUserWallet();
        $this->financeDiamondModel = new FinanceDiamond();
        $this->financeEnergyModel = new FinanceEnergy();
        $this->financeEnergyCoinModel = new FinanceEnergyCoin();
        $this->giftBag_model = new GiftBag();
        $this->mallModel = new Mall();
        $this->angerbirdModel = new Angerbird();
        $this->msgService = new MsgServices();
        $this->roomMsgService = new RoomMsgServices();
        $this->model_system = new System();

    }

    /**
     * 开始新一局游戏并持续处理
     */
    public function gameHandle()
    {
        $i = 0;
        //起飞动画时间
        $flyStartSecond = 1.5;
        //结果展示阶段时间
        $endNum = 4;
        //初始高度
        $heightBase = 100;
        //最高高度
        $maxHeight = $this->maxHeight;
        //奖励高度启示
        $rewardHeight = $this->rewardHeight;

        //获取配置
        $config = $this->angerbirdModel->getConfig();
        //局数
        $gameNum = $this->_getGameNum();
        if(empty($gameNum) || empty($config)) {
            write_log($this->errorLogName, 'ERROR 愤怒的小鸟每局数据处理 配置获取失败', ['game_num'=>$gameNum, 'config'=>$config]);
            return 2;
        }
        $config = array_column($config, 'value', 'key');

        do {
            try{
                //游戏一开始时候的处理 倒计时10
                if($i == 0) {
                    $i++;
                    //局数增加
                    Redis::INCRBY($this->gameNumKey, 1);
                    //新的局数
                    $gameNum = $this->_getGameNum();
                    //游戏阶段
                    $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
                    Redis::SET($gameStatusKey, 1);
                    Redis::expire($gameStatusKey, $this->cacheExpire);
                    //飞行高度
                    $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
                    Redis::SET($gameHeightKey, 0);
                    Redis::expire($gameHeightKey, $this->cacheExpire);
                    //倒计时
                    $gameCountdownNumKey = $this->makeKey($this->gameCountdownNumKey, $gameNum);
                    Redis::SET($gameCountdownNumKey, $this->countdownNum);
                    Redis::expire($gameCountdownNumKey, $this->cacheExpire);
                    //游戏信息
                    $this->angerBirdMsg(2, $gameNum, 0);
                    //停1秒
                    sleep(1);
                    continue;
                }

                //游戏阶段
                $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
                $gameStatus = Redis::GET($gameStatusKey);
                //倒计时
                $gameCountdownNumKey = $this->makeKey($this->gameCountdownNumKey, $gameNum);
                //飞行高度
                $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
                //已押注用户数量
                $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
                //已兑换用户数量
                $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);

                //倒计时阶段
                if($gameStatus == 1) {
                    //倒计时
                    $countdownNum = (int) Redis::GET($gameCountdownNumKey);
                    if($countdownNum > 1) {
                        Redis::DECRBY($gameCountdownNumKey, 1);
                        //游戏信息
                        $this->angerBirdMsg(2, $gameNum, 0);
                        //停1秒
                        sleep(1);
                    }else{
                        Redis::DECRBY($gameCountdownNumKey, 1);
                        //进入下一游戏阶段
                        Redis::SET($gameStatusKey, 2);
                        $gameStatus = Redis::GET($gameStatusKey);
                        //游戏信息
                        $this->angerBirdMsg(2, $gameNum, 0);
                    }
                }

                //起飞阶段
                if($gameStatus == 2) {
                    //进入下一游戏阶段
                    Redis::SET($gameStatusKey, 3);
                    $gameStatus = Redis::GET($gameStatusKey);
                    //起飞动画时间
                    usleep($flyStartSecond * 1000000);
                    //飞行高度
                    Redis::SET($gameHeightKey, $heightBase);
                }

                //飞行阶段
                if($gameStatus == 3) {
                    //飞行高度
                    $gameHeight = Redis::GET($gameHeightKey);
                    //初始位置
                    if($gameHeight == $heightBase) {
                        //游戏信息
                        $this->angerBirdMsg(3, $gameNum, 0);
                        usleep(100000);//100毫秒
                        //飞行高度 增加
                        $gameHeight = $gameHeight + 1;
                        Redis::SET($gameHeightKey, $gameHeight);
                        //游戏信息
                        $this->angerBirdMsg(3, $gameNum, 0);
                        usleep(100000);//100毫秒
                        $i++;
                        continue;
                    }
                    //飞起来了
                    //已押注用户数量
                    $stakeUserNum = (int) Redis::ZCARD($allUserStakeKey);
                    //不存在押注
                    if(empty($stakeUserNum)) {
                        if($gameHeight>=100 && $gameHeight<200) {
                            $step = 1;
                        }elseif($gameHeight>=200 && $gameHeight<1000) {
                            $step = rand(1,7);
                        }elseif($gameHeight>=1000 && $gameHeight<2000) {
                            $step = rand(3,25);
                        }elseif($gameHeight>=1000 && $gameHeight<4000) {
                            $step = rand(7,77);
                        }elseif($gameHeight>=4000) {
                            $step = rand(17,193);
                        }
                        //飞行高度 增加
                        $newHeight = $gameHeight + $step;
                        Redis::SET($gameHeightKey, $newHeight);
                        //超过该停止了
                        $topHeight = mt_rand(($gameHeight+1), $maxHeight);
                        if($newHeight >= $topHeight) {
                            //进入下一游戏阶段
                            Redis::SET($gameStatusKey, 4);
                            $gameStatus = Redis::GET($gameStatusKey);
                        }
                        //游戏信息
                        $this->angerBirdMsg(3, $gameNum, 0);
                        usleep(100000);//100毫秒
                        // TODO 调试 注释
                        sleep(1);
                        $i++;
                        continue;
                    }
                    //存在押注
                    if($stakeUserNum > 0) {
                        $time1 = microtime(true);
                        //已兑换用户数量
                        $rewardUserNum = (int) Redis::ZCARD($allUserRewardKey);
                        //游戏开始后当本局待兑换人数为0时
                        if($stakeUserNum <= $rewardUserNum) {
                            $topHeight = mt_rand(($gameHeight+1), $maxHeight);
                        }else{
                            //可抵达最高高度 100范围内检索
                            $topHeight = $this->_mathResult($gameNum, $gameHeight, $config, $rewardHeight);
                        }
                        if($gameHeight>=100 && $gameHeight<200) {
                            $step = 1;
                        }elseif($gameHeight>=200 && $gameHeight<1000) {
                            $step = rand(1,7);
                        }elseif($gameHeight>=1000 && $gameHeight<2000) {
                            $step = rand(3,25);
                        }elseif($gameHeight>=1000 && $gameHeight<4000) {
                            $step = rand(7,77);
                        }elseif($gameHeight>=4000) {
                            $step = rand(17,193);
                        }
                        //超过该停止了
                        $newHeight = $gameHeight + $step;
                        if($newHeight >= $topHeight) {
                            if($topHeight>0 && $topHeight>$gameHeight) {
                                $newHeight = $topHeight - 1;
                            }else{
                                $newHeight = $gameHeight;
                            }
                            //进入下一游戏阶段
                            Redis::SET($gameStatusKey, 4);
                            $gameStatus = Redis::GET($gameStatusKey);
                        }
                        //飞行高度 增加
                        Redis::SET($gameHeightKey, $newHeight);
                        //游戏信息
                        $this->angerBirdMsg(3, $gameNum, 0);
                        //自动兑换
                        $this->_rewardGameUser($gameNum, $config);
                        $time2 = microtime(true);
                        $timeDiff = intval(($time2-$time1)*100);//消耗的毫秒
                        if($timeDiff < 100) {
                            usleep((100-$timeDiff)*1000);
                        }
                        // TODO 调试 注释
                        sleep(1);
                        $i++;
                    }
                }

                //结果展示阶段
                if($gameStatus == 4) {
                    //生成统计数据
                    $this->_makeStat($gameNum, $config);
                    //飘屏
                    $this->_sendFullScreen($gameNum, $config);
                    for($i=0;$i<$endNum;$i++) {
                        sleep(1);
                        if($i == ($endNum-1)) {
                            continue;
                        }
                        //游戏信息
                        $this->angerBirdMsg(3, $gameNum, 0);
                    }
                    $i = 0;
                    break;
                }

            }catch(\Exception $e){
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟每局数据处理 异常', ['msg'=>$e->getMessage(), 'line'=>$e->getLine()]);
                break;
            }
            $i++;

        } while (true);

        return 1;
    }

    /**
     * 计算当前游戏结果
     */
    protected function _mathResult($gameNum, $nowHeight, $config, $rewardHeight)
    {
        //押注池新增
        $trackPoolIncr = 0;

        //押注池剩余金额
        $trackPoolTotal = Redis::GET($this->trackPoolTotalKey);

        //用户押注
        $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
        $stakeList = Redis::HGETALL($userStakeKey);

        //押注数据整理
        $heightMap = [];
        foreach($stakeList as $key=>$val) {
            $val = json_decode($val, true);
            $stakeList[$key] = $val;
            $trackPoolIncr = $trackPoolIncr + $val['basePrice'];

            $h = empty($val['r_height']) ? $val['height'] : $val['r_height'];
            if(empty($heightMap[$h])) {
                $heightMap[$h]['height'] = $h;
                $heightMap[$h]['rewardPrice'] = $val['rewardPrice'];
                $heightMap[$h]['basePrice'] = $val['basePrice'];
            }else{
                $heightMap[$h]['rewardPrice'] = $heightMap[$h]['rewardPrice'] + $val['rewardPrice'];
                $heightMap[$h]['basePrice'] = $heightMap[$h]['basePrice'] + $val['basePrice'];
            }
        }
        array_multisort(array_column($heightMap, 'height'), SORT_ASC, $heightMap);

        //计算指定高度是否需要终止游戏
        $stopHeight = 0;
        for($i=1;$i<100;$i++) {
            $heightNum = $i + $nowHeight;
            $res = $this->_checkHeightToStopGame($heightNum, $config, $trackPoolTotal, $heightMap, $trackPoolIncr);
            if($res == 1) {
                $stopHeight = $heightNum;
            }else{
                break;
            }
        }

        if($stopHeight < $rewardHeight) {
            $stopHeight = rand(($stopHeight-5), ($stopHeight-1));
        }

        return $stopHeight;
    }

    /**
     * 计算指定高度是否需要终止游戏
     */
    protected function _checkHeightToStopGame($hopeHeight, $config, $trackPoolTotal, $heightMap, $trackPoolIncr)
    {
        //根据期望高度整理奖励
        $rewardNum = 0;
        foreach($heightMap as $key=>$val) {
            if($val['height'] > $hopeHeight) {
                $rewardPrice = round(($hopeHeight*$val['basePrice'])/100);
            }else{
                $rewardPrice = $val['rewardPrice'];
            }

            $val['use_rewardPrice'] = $rewardPrice;
            $heightMap[$key] = $val;

            $rewardNum = $rewardNum + $rewardPrice;
        }

        //利润池新增
        $profitPoolIncr = intval(($trackPoolIncr*$config['angerbird_profit_rate'])/100);
        //押注池新增
        $trackPoolIncr = $trackPoolIncr - $profitPoolIncr;

        //押注池总值
        $trackPoolTotal = $trackPoolTotal + $trackPoolIncr;

        //押注池下限
        $rewardMin = intval($trackPoolTotal*$config['angerbird_reward_min']*0.01);

        //是否可赔付
        $res = 1;
        if($trackPoolTotal < 0) {
            $res = 0;
        }elseif(($trackPoolTotal-$rewardMin) <= $rewardNum) {
            $res = 0;
        }

        return $res;
    }

    /**
     * 根据当前高度自动兑换
     */
    protected function _rewardGameUser($gameNum)
    {
        $now = time();
        //飞行高度
        $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
        $gameHeight = Redis::GET($gameHeightKey);
        //获取押注
        $stakeList = $this->angerbirdModel->getAngerbirdLogByGameNum($gameNum, $gameHeight);

        //用户押注信息
        $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
        //某局兑换的所有用户
        $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);
        //某局已兑换的能量币总值
        $allEnergyCoinRewardKey = $this->makeKey($this->allEnergyCoinRewardKey, $gameNum);
        //处理
        foreach($stakeList as $val) {
            //锁
            $ifLock = redis_lock($this->activityPromotionLockKey."REWARD:".$gameNum.'|'.$val['user_id'], 60);
            if(!$ifLock) {
                continue;
            }
            $userId = $val['user_id'];

            $log = [
                'game_num' => $gameNum,
                'user_id' => $userId,
                'height' => $val['height'],
                'r_height' => $val['height'],
                'stakeCount' => $val['stakeCount'],
                'basePrice' => $val['basePrice'],
                'rewardPrice' => $val['rewardPrice'],
                'status' => 1,
            ];

            DB::beginTransaction();
            try{
                //加能量币
                $this->financeEnergyCoinModel->inc($userId, $gameNum, 1, $val['rewardPrice'], '押注奖励');

                //更新
                $res = $this->angerbirdModel->updateLog($gameNum, $userId, ['status'=>1, 'r_height'=>$val['height']]);
                if(!$res) {
                    DB::rollBack();
                    continue; 
                }

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 根据当前高度自动兑换失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'val'=>$val, 'game_num'=>$gameNum]);
                continue;
            }

            //用户押注信息
            Redis::HSET($userStakeKey, $userId, json_encode($log));
            //某局兑换的所有用户
            Redis::ZADD($allUserRewardKey, $now, $userId);
            Redis::expire($allUserRewardKey, $this->cacheExpire);
            //某局已兑换的能量币总值
            Redis::INCRBY($allEnergyCoinRewardKey, $val['rewardPrice']);
            Redis::expire($allEnergyCoinRewardKey, $this->cacheExpire);

            //游戏信息
            $this->angerBirdMsg(4, $gameNum, $userId);
        }
    }

    /**
     * 生成统计数据
     */
    public function _makeStat($gameNum, $config)
    {
        //飞行高度
        $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
        $gameHeight = Redis::GET($gameHeightKey);

        //获取统计数据
        $gameInfoWin = $this->angerbirdModel->getGameSumByGameNumWin($gameNum);
        $gameInfoAll = $this->angerbirdModel->getGameSumByGameNum($gameNum);
        //利润率
        $porfitRate = $config['angerbird_profit_rate']/100;
        //本局比赛抽水
        $porfitPrice = round($gameInfoAll['basePrice'] * $porfitRate);
        //押注池新增
        $stakePoolAll = $gameInfoAll['basePrice'] - $porfitPrice - $gameInfoWin['rewardPrice'];

        //押注池
        Redis::INCRBY($this->trackPoolTotalKey, $stakePoolAll);
        //利润池
        Redis::INCRBY($this->profitTotalKey, $porfitPrice);

        $log = [];
        $log['gameNum'] = (int) $gameNum;//游戏局数
        $log['winner'] = (int) $gameHeight;//结果
        $log['ymd'] = date("Ymd");//日期
        $log['stakeNumAll'] = (int) $gameInfoAll['stakeCount'];//押注次数(总)
        $log['stakeUserAll'] = (int) $gameInfoAll['userNum'];//押注用户数(总)
        $log['stakePriceAll'] = (int) $gameInfoAll['basePrice'];//押注数量(总)
        $log['rewardPriceAll'] = (int) $gameInfoWin['rewardPrice'];//奖励数量(总)
        $log['stakeNum'] = (int) $gameInfoWin['stakeCount'];//押注次数(中奖)
        $log['stakeUser'] = (int) $gameInfoWin['userNum'];//押注用户数(中奖)
        $log['porfitPoolAll'] = (int) $porfitPrice;//利润池新增
        $log['stakePoolAll'] = $stakePoolAll;//押注池新增
        $log['porfitRate'] = 100*$porfitRate;//利润率
        $log['stakePoolRateMin'] = $config['angerbird_reward_min'];//赔付池下限百分比%
        $log['trackPoolTotal'] = (int) Redis::GET($this->trackPoolTotalKey);//比赛结束押注池剩余
        $log['profitTotal'] = (int) Redis::GET($this->profitTotalKey);//比赛结束利润池剩余

        try {
            $id = $this->angerbirdModel->createStatLog($log);
            if(!$id) {
                write_log($this->errorLogName, 'ERROR 统计数据记录失败', ['gameNum'=>$gameNum, 'log'=>$log]); 
            }
        } catch (\Exception $e) {
            write_log($this->errorLogName, 'ERROR 统计数据记录失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'gameNum'=>$gameNum, 'log'=>$log]); 
        }
    }

    /**
     * 飘屏
     */
    public function _sendFullScreen($gameNum, $config)
    {
        $list = $this->angerbirdModel->getAngerbirdLogWin($gameNum, 5);
        if(!empty($list)) {
            $userIds = array_column($list, 'user_id');

            //用户信息
            $userList = $this->userModel->get_users_by_ids($userIds);
            $userList = array_column($userList, null, 'user_id');

            foreach($list as $val) {
                if(empty($userList[$val['user_id']])) {
                    continue;
                }
                //普通飘屏
                $this->msgService->sendFullScreen(75, null, ['userName'=>$userList[$val['user_id']]['nickname'], 'energy_coin'=>$val['rewardPrice']],[],['giftPrice'=>$val['rewardPrice']]);

//                $spFullScreen = $this->model_system->getFullScreen(74);//特殊票屏信息
//
//                //高级世界飘屏
//                if($val['rewardPrice'] >= $spFullScreen['special_full_screen_diamond'] && $spFullScreen['special_full_screen_diamond'] != 0){
//                    $this->msgService->sendFullScreen(74, null, ['userName'=>$userList[$val['user_id']]['nickname'], 'energy_coin'=>$val['rewardPrice']],[],['giftPrice'=>$val['rewardPrice']]);
//                }
            }
        }
    }

    /**
     * 获取当前游戏局数
     */
    protected function _getGameNum()
    {
        $gameNum = Redis::GET($this->gameNumKey);

        return (int) $gameNum;
    }

    /**
     * 拼组KEY
     * @return bool
     */
    public function makeKey($key, $str1='', $str2='', $str3='', $str4='', $str5='')
    {
        $result = $key;
        if(!empty($str1)) {
            $result = $result . $str1;
        }
        if(!empty($str2)) {
            $result = $result . ':' . $str2;
        }
        if(!empty($str3)) {
            $result = $result . ':' . $str3;
        }
        if(!empty($str4)) {
            $result = $result . ':' . $str4;
        }
        if(!empty($str5)) {
            $result = $result . ':' . $str5;
        }

        return $result;
    }

    /**
     * 愤怒的小鸟配置修改
     */
    public function angerbirdUpdateConfig($key, $val)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            $this->angerbirdModel->updateConfig($key, $val);

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟新增商店
     */
    public function angerbirdAddShop($giftId, $energyCoin, $ifShow)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            //是否存在
            $info = $this->angerbirdModel->getAngerbirdShopByGiftId($giftId);
            if(!empty($info)) {
                $code = Hint::PARAM_ERROR;
                $msg = '礼物已存在不可新增';
                break;
            }

            $this->angerbirdModel->angerbirdAddShop($giftId, $energyCoin, $ifShow);

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟修改商店
     */
    public function angerbirdUpdateShop($shopId, $energyCoin, $ifShow)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            //是否存在
            $info = $this->angerbirdModel->getAngerbirdShopById($shopId);
            if(empty($info)) {
                $code = Hint::PARAM_ERROR;
                $msg = '数据不存在无法编辑';
                break;
            }

            $this->angerbirdModel->angerbirdUpdateShop($shopId, ['energy_coin'=>$energyCoin, 'if_show'=>$ifShow]);

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟游戏配置获取
     */
    public function angerbirdGetConfig($userId){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNum = $this->_getGameNum();
            //已押注用户数量
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            $stakeUserNum = (int) Redis::ZCARD($allUserStakeKey);
            //已兑换用户数量
            $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);
            $rewardUserNum = (int) Redis::ZCARD($allUserRewardKey);
            //某局已兑换的能量币总值
            $allEnergyCoinRewardKey = $this->makeKey($this->allEnergyCoinRewardKey, $gameNum);
            $energyCoinRewardNum = (int) Redis::GET($allEnergyCoinRewardKey);
            //本局押注用户列表
            $stakeUserList = $this->angerbirdUserList();
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            //倒计时
            $gameCountdownNumKey = $this->makeKey($this->gameCountdownNumKey, $gameNum);
            $countdownNum = (int) Redis::GET($gameCountdownNumKey);
            //飞行高度
            $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
            $gameHeight = (int) Redis::GET($gameHeightKey);
            //结果记录
            $resList = $this->angerbirdResList(10);

            //游戏房间ID
            $data['room_id'] = $this->gameRoomId;
            //当前局数
            $data['game_num'] = $gameNum;
            //商品ID
            $data['angerbird_good_id'] = $config['angerbird_good_id'];
            //商品钻石价格
            $data['angerbird_good_price'] = $config['angerbird_good_price'];
            //用户本局押注
            $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNum, 1);
            //用户下一局押注
            $data['user_stake_next'] = $this->angerbirdGetUserStake($userId, ($gameNum+1), 1);
            //已押注用户数量
            $data['stake_user_num'] = $stakeUserNum;
            //已兑换用户数量
            $data['reward_user_num'] = $rewardUserNum;
            //某局已兑换的能量币总值
            $data['energy_coin_reward_num'] = $energyCoinRewardNum;
            //本局押注用户列表
            $data['stake_user_list'] = $stakeUserList['data']['list'];
            //当前游戏阶段
            $data['game_status'] = $gameStatus;
            //倒计时
            $data['countdown_num'] = $countdownNum;
            //当前飞行高度
            $data['n_height'] = $gameHeight;
            //胜利高度列表
            $data['res_list'] = $resList['data']['list'];
            //玩法介绍
            $data['rule'] = '1、用户每购买一个头像框，赠送100能量，能量可用于【投入】愤怒的小鸟，每轮最少投入100个能量。
                2、游戏开始前，玩家需要投入能量和选择小鸟飞行高度，操作完毕后点击投入即本轮游戏参与成功。投入能量后可再次对投入的能量进行叠加或撤销本次投入的能量。
                3、游戏开始后，本轮能量停止投入，小鸟高度会从1.00x开始增长。飞行高度升高过程中，小鸟随时可能爆炸，即游戏结束。
                4、玩家可在小鸟爆炸前，可随时点击【兑换能量】提前结束本轮游戏，此时【收获的能量币=投入能量x飞行高度】。在结束本轮游戏的同时可对下一轮游戏进行【提前投入能量】。
                5、飞行高度最高为99.00x，小鸟飞行高度会随时间不断变化，可能会因网络延迟原因导致玩家获得的能量币的飞行高度与操作时所见的高度存在差异，系统会按照实际接收到的结果作为最终判断。
                6、在愤怒的小鸟中收获的能量币（1能量=1能量币）可在小鸟商店中兑换礼物、道具等物品存入背包，一经兑换成功不可撤销。
                7、愤怒的小鸟用于丰富语音房玩法，仅供娱乐交流使用。用户获得的随机礼物仅限于平台内互动娱乐使用，不得以任何形式兑换成法定货币、现金、或其他任何具有交换价值的物品或服务，任何违规行为一经发现，平台将严格按规定对违规账号进行封禁处理。
                5、对于任何违规手段或影响公共性的行为，经查证属实，官方有权终止向违规账号提供服务，回收账号并清空账号中的非法虚拟产品；情节严重者平台有权追究相关法律责任。
                6、本活动与苹果公司无关，最终解释权归OT派对所有。';

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟获取用户指定局数押注信息
     */
    public function angerbirdGetUserStake($userId, $gameNum, $needUserInfo=0){
        $data = [];
        do {
            //用户本局押注
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            $stakeInfo = Redis::HGET($userStakeKey, $userId);
            $data = empty($stakeInfo) ? [] : json_decode($stakeInfo, true);
            if(empty($data)) {
                $data = [
                    'game_num' => $gameNum,
                    'user_id' => $userId,
                    'height' => 0,
                    'r_height' => 0,
                    'stakeCount' => 0,
                    'basePrice' => 0,
                    'rewardPrice' => 0,
                    'status' => 0,
                ];
            }
            if($needUserInfo == 1) {
                $userList = $this->userModel->get_users_by_ids([$userId]);
                if(!empty($userList)) {
                    $data['nickname'] = $userList[0]['nickname'];
                    $data['avatar'] = build_image($userList[0]['images'][0]);
                }
            }

        } while (false);

        return $data;
    }

    /**
     * 愤怒的小鸟兑换商店列表
     */
    public function angerbirdGetShopList($userId){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            $list = $this->angerbirdModel->getAngerbirdShopList();
            $data['list'] = $list;

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟兑换商店兑换
     */
    public function angerbirdShopBuy($userId, $shopId, $giftNum){
        $code = Hint::SUCCESS;
        $msg = '兑换成功';
        $data = [];
        do {
            //是否存在
            $info = $this->angerbirdModel->getAngerbirdShopById($shopId);
            if(empty($info)) {
                $code = Hint::PARAM_ERROR;
                $msg = '商品不存在,请刷新';
                break;
            }
            if($info['if_show'] != 1) {
                $code = Hint::PARAM_ERROR;
                $msg = '商品已下架,请刷新';
                break;
            }
            $needNum = $info['energy_coin'] * $giftNum;
            //查看用户钱包
            $userWaltInfo = $this->userWalletModel->get_wallet($userId);
            if($userWaltInfo['energy_coin'] < $needNum){
                $code = Hint::DIAMOND_NOT_ENOUGH;
                $msg = '当前能量币不足';
                break;
            }

            DB::beginTransaction();
            try{
                //扣能量币
                $this->financeEnergyCoinModel->inc($userId, $info['gift_id'], 101, $needNum, '商店兑换扣除');

                //送礼物
                $this->giftBag_model->inc($userId, 0, $info['gift_id'], $giftNum, 10003);

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟兑换商店兑换失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'shopId'=>$shopId, 'giftNum'=>$giftNum]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常,兑换失败';
                break;
            }

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟兑换商店记录列表
     */
    public function angerbirdGetShopLog($userId, $page, $limit){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            $listEx = [];
            $list = $this->financeEnergyCoinModel->energyCoinList($page, $limit, ['user_id'=>$userId, 'energy_coin_type'=>101]);
            if(!empty($list)) {
                $giftIds = array_column($list, 'data_id');
                $giftList = $this->giftModel->getGiftByGiftIds($giftIds,['gift_id','name','image','price']);
                $giftList = array_column($giftList, null, 'gift_id');

                foreach($list as $key=>$val) {
                    if(empty($giftList[$val['data_id']])) {
                        continue;
                    }

                    $item = [];
                    $item['gift_id'] = $val['data_id'];
                    $item['user_id'] = $val['user_id'];
                    $item['gift_name'] = $giftList[$val['data_id']]['name'];
                    $item['gift_image'] = build_image($giftList[$val['data_id']]['image']);
                    $item['gift_price'] = $giftList[$val['data_id']]['price'];
                    $item['energy_coin'] = abs($val['change_value']);
                    $item['created_at'] = date('Y-m-d', strtotime($val['created_at']));
                    $listEx[] = $item;
                }
            }

            $data['list'] = $listEx;

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟购买能量
     */
    public function angerbirdBuyEnergy($userId, $num){
        $code = Hint::SUCCESS;
        $msg = '兑换成功';
        $data = [];
        do {
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            $angerBirdGoodId = $config['angerbird_good_id'];
            $price = $config['angerbird_good_price'];
            $needNum = abs($price * $num);
            if(empty($angerBirdGoodId) || empty($needNum)) {
                $code = Hint::PARAM_ERROR;
                $msg = '系统配置异常:配置错误';
                break;
            }

            //查看用户钱包
            $userWaltInfo = $this->userWalletModel->get_wallet($userId);
            if($userWaltInfo['diamond_balance'] < $needNum){
                $code = Hint::DIAMOND_NOT_ENOUGH;
                break;
            }
            $pay = config('pay');
            $diamond_desc = $pay['wallet_change_desc']['diamond_angerbird_decr'];
            $energyNum = $needNum * 10;

            //商品信息
            $goodInfo = $this->mallModel->getMallGoodByGoodsId($angerBirdGoodId);
            if(empty($goodInfo)) {
                $code = Hint::PARAM_ERROR;
                $msg = '系统配置异常:商品不存在';
                break;
            }
            $skuList = $this->mallModel->getSkuDataByGoods($angerBirdGoodId);
            if(empty($skuList[0])) {
                $code = Hint::PARAM_ERROR;
                $msg = '系统配置异常:商品信息异常';
                break;
            }
            $goodInfo['sku_id'] = $skuList[0]['sku_id'];
            //有效期
            $timeLimit = $num * 3600;

            DB::beginTransaction();
            try{
                //扣钻石
                $this->financeDiamondModel->inc($userId, 0, 0, 91, 0-$needNum, $diamond_desc);

                //加能量
                $this->financeEnergyModel->inc($userId, 0, 1, $energyNum, '愤怒的小鸟-获得能量');

                //送商品
                $this->mallModel->shoppingAct(
                    $userId,
                    $userId,
                    $angerBirdGoodId,
                    $goodInfo['goods_name'],
                    $goodInfo['goods_type'],
                    $goodInfo['sku_id'],
                    $timeLimit,
                    0,
                    $timeLimit,
                    time(),
                    1
                );

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                $eer = ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'num'=>$num];
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟购买能量失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'num'=>$num]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常,购买失败';
                break;
            }

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟游戏消息
     * type 1=押注消息 2=倒计时变化 3=飞行高度变化 4=用户兑换能量币消息
     */
    public function angerBirdMsg($type, $gameNum, $userId=0){
        do {
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            //已押注用户数量
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            $stakeUserNum = (int) Redis::ZCARD($allUserStakeKey);
            //已兑换用户数量
            $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);
            $rewardUserNum = (int) Redis::ZCARD($allUserRewardKey);
            //某局已兑换的能量币总值
            $allEnergyCoinRewardKey = $this->makeKey($this->allEnergyCoinRewardKey, $gameNum);

            $data = [];
            $data['type'] = $type;
            $data['game_num'] = $gameNum;
            $data['game_status'] = $gameStatus;
            $data['stake_user_num'] = $stakeUserNum;
            $data['reward_user_num'] = $rewardUserNum;
            $data['energy_coin_reward_num'] = 0;

            //押注消息
            if($type == 1) {
                //某局已兑换的能量币总值
                $data['energy_coin_reward_num'] = (int) Redis::GET($allEnergyCoinRewardKey);
                //用户本局押注
                $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNum, 1);
            }

            //倒计时变化
            if($type == 2) {
                //倒计时
                $gameCountdownNumKey = $this->makeKey($this->gameCountdownNumKey, $gameNum);
                $data['countdown_num'] = (int) Redis::GET($gameCountdownNumKey);
                //第一次倒计时 给押注列表
                if($data['countdown_num'] == $this->countdownNum) {
                    //本局押注用户列表
                    $stakeUserList = $this->angerbirdUserList();
                    //本局押注用户列表
                    $data['stake_user_list'] = $stakeUserList['data']['list'];
                }
            }

            //飞行高度变化
            if($type == 3) {
                //某局已兑换的能量币总值
                $data['energy_coin_reward_num'] = (int) Redis::GET($allEnergyCoinRewardKey);
                //飞行高度
                $gameHeightKey = $this->makeKey($this->gameHeightKey, $gameNum);
                $data['n_height'] = (int) Redis::GET($gameHeightKey);
            }

            //用户兑换能量币消息
            if($type == 4) {
                //某局已兑换的能量币总值
                $data['energy_coin_reward_num'] = (int) Redis::GET($allEnergyCoinRewardKey);
                //用户本局押注
                $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNum, 1);
            }

            $this->roomMsgService->angerBirdMsg($this->gameRoomId, $data);
        } while (false);
    }

    /**
     * 愤怒的小鸟用户初始押注
     */
    public function angerbirdUserFirstStake($userId, $height, $energyNum, $gameNum){
        $code = Hint::SUCCESS;
        $msg = '投入成功';
        $data = [];
        $now = time();

        do {
            //18点到24点开放
            $h = date('H');
            if($h < 18) {
                // $code = Hint::PARAM_ERROR;
                // $msg = '限时开放 18点至24点';
                // break;
            }

            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNumNow = $this->_getGameNum();
            if($gameNum != $gameNumNow) {
                $code = Hint::PARAM_ERROR;
                $msg = '本局已结束无法押注';
                break;
            }
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            if($gameStatus != 1) {
                $code = Hint::PARAM_ERROR;
                $msg = '游戏已开始，无法投入';
                break;
            }
            //押注过请求叠加押注
            $userStake = $this->angerbirdGetUserStake($userId, $gameNum);
            if(!empty($userStake['height'])) {
                return $this->angerbirdUserStake($userId, $energyNum, $gameNum);
            }
            //获取用户钱包信息
            $userWaltInfo = $this->userWalletModel->get_wallet($userId);
            if($userWaltInfo['energy'] < $energyNum){
                $code = Hint::PEARL_NOT_ENOUGH;
                $msg = '当前能量不足';
                break;
            }

            $log = [
                'game_num' => $gameNum,
                'user_id' => $userId,
                'height' => $height,
                'r_height' => 0,
                'stakeCount' => 1,
                'basePrice' => $energyNum,
                'rewardPrice' => round(($height*$energyNum)/100),
                'status' => 0,
            ];

            DB::beginTransaction();
            try{
                //扣能量
                $this->financeEnergyModel->inc($userId, $gameNum, 101, $energyNum, '愤怒的小鸟-押注扣除');

                //记录
                $this->angerbirdModel->createLog($log);

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟用户初始押注失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'height'=>$height, 'game_num'=>$gameNum, 'energyNum'=>$energyNum]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常';
                break;
            }

            //用户押注信息
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            Redis::HSET($userStakeKey, $userId, json_encode($log));
            Redis::expire($userStakeKey, $this->cacheExpire);
            //某局所有用户押注信息
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            Redis::ZADD($allUserStakeKey, $now, $userId);
            Redis::expire($allUserStakeKey, $this->cacheExpire);

            //游戏信息
            if($gameNum == $gameNumNow) {
                $this->angerBirdMsg(1, $gameNumNow, $userId);
            }
        } while (false);

        //用户本局押注
        $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNumNow, 1);
        //用户下一局押注
        $data['user_stake_next'] = $this->angerbirdGetUserStake($userId, ($gameNumNow+1), 1);
        $data['game_num'] = $gameNum;

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟用户叠加押注
     */
    public function angerbirdUserStake($userId, $energyNum, $gameNum){
        $code = Hint::SUCCESS;
        $msg = '投入成功';
        $data = [];
        $now = time();

        do {
            //18点到24点开放
            $h = date('H');
            if($h < 18) {
                // $code = Hint::PARAM_ERROR;
                // $msg = '限时开放 18点至24点';
                // break;
            }

            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNumNow = $this->_getGameNum();
            if($gameNum != $gameNumNow) {
                $code = Hint::PARAM_ERROR;
                $msg = '本局已结束无法押注';
                break;
            }
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            if($gameStatus != 1) {
                $code = Hint::PARAM_ERROR;
                $msg = '游戏已开始，无法投入';
                break;
            }
            //没有押注过
            $userStake = $this->angerbirdGetUserStake($userId, $gameNum);
            if(empty($userStake['height'])) {
                $code = Hint::PARAM_ERROR;
                $msg = '用户押注信息获取失败';
                break;
            }
            //获取用户钱包信息
            $userWaltInfo = $this->userWalletModel->get_wallet($userId);
            if($userWaltInfo['energy'] < $energyNum){
                $code = Hint::PEARL_NOT_ENOUGH;
                $msg = '当前能量不足';
                break;
            }

            $log = [
                'game_num' => $gameNum,
                'user_id' => $userId,
                'height' => $userStake['height'],
                'r_height' => 0,
                'stakeCount' => $userStake['basePrice']+1,
                'basePrice' => $userStake['basePrice']+$energyNum,
                'rewardPrice' => round(($userStake['height']*($userStake['basePrice']+$energyNum))/100),
                'status' => 0,
            ];

            DB::beginTransaction();
            try{
                //扣能量
                $this->financeEnergyModel->inc($userId, $gameNum, 101, $energyNum, '愤怒的小鸟-押注扣除');

                //更新
                $res = $this->angerbirdModel->updateLog($gameNum, $userId, ['basePrice'=>$log['basePrice'], 'rewardPrice'=>$log['rewardPrice'], 'stakeCount'=>$log['stakeCount']]);
                if(!$res) {
                    DB::rollBack();
                    $code = Hint::ERR_NORMAL;
                    $msg = '押注失败';
                    break; 
                }

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟用户叠加押注失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'game_num'=>$gameNum, 'energyNum'=>$energyNum]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常';
                break;
            }

            //用户押注信息
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            Redis::HSET($userStakeKey, $userId, json_encode($log));
            //某局所有用户押注信息
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            Redis::ZADD($allUserStakeKey, $now, $userId);

            //游戏信息
            if($gameNum == $gameNumNow) {
                $this->angerBirdMsg(1, $gameNumNow, $userId);
            }

        } while (false);

        //用户本局押注
        $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNumNow, 1);
        //用户下一局押注
        $data['user_stake_next'] = $this->angerbirdGetUserStake($userId, ($gameNumNow+1), 1);
        $data['game_num'] = $gameNum;

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟用户撤销押注
     */
    public function angerbirdUserStakeBack($userId, $gameNum){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNumNow = $this->_getGameNum();
            if($gameNum < $gameNumNow) {
                $code = Hint::PARAM_ERROR;
                $msg = '游戏已结束，无法撤销';
                break;
            }
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            if(($gameNum==$gameNumNow) && ($gameStatus!=1)) {
                $code = Hint::PARAM_ERROR;
                $msg = '游戏已开始，无法撤销';
                break;
            }
            //没有押注过
            $userStake = $this->angerbirdGetUserStake($userId, $gameNum);
            if(empty($userStake['height'])) {
                break;
            }

            DB::beginTransaction();
            try{
                //加能量
                $this->financeEnergyModel->inc($userId, $gameNum, 2, $userStake['basePrice'], '愤怒的小鸟-押注撤销');

                //更新
                $res = $this->angerbirdModel->updateLog($gameNum, $userId, ['is_delete'=>1]);
                if(!$res) {
                    DB::rollBack();
                    $code = Hint::ERR_NORMAL;
                    $msg = '撤销押注失败';
                    break; 
                }

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟用户撤销押注失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'game_num'=>$gameNum]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常';
                break;
            }

            //用户押注信息
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            Redis::HDEL($userStakeKey, $userId);
            //某局所有用户押注信息
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            Redis::ZREM($allUserStakeKey, $userId);

            //游戏信息
            if($gameNum == $gameNumNow) {
                $this->angerBirdMsg(1, $gameNumNow, $userId);
            }

        } while (false);

        //用户本局押注
        $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNumNow, 1);
        //用户下一局押注
        $data['user_stake_next'] = $this->angerbirdGetUserStake($userId, ($gameNumNow+1), 1);
        $data['game_num'] = $gameNum;

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟用户兑换能量币
     */
    public function angerbirdUserReward($userId, $gameNum, $height){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            if($height < $this->rewardHeight) {
                $code = Hint::PARAM_ERROR;
                $msg = '未达到可兑换高度';
                break;
            }
            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNumNow = $this->_getGameNum();
            if($gameNum != $gameNumNow) {
                $code = Hint::PARAM_ERROR;
                $msg = '本局游戏已结束';
                break;
            }
            //游戏阶段
            $gameStatusKey = $this->makeKey($this->gameStatusKey, $gameNum);
            $gameStatus = (int) Redis::GET($gameStatusKey);
            if($gameStatus != 3) {
                $code = Hint::PARAM_ERROR;
                $msg = '本局游戏未开始';
                break;
            }
            //没有押注过
            $userStake = $this->angerbirdGetUserStake($userId, $gameNum);
            if(empty($userStake['height'])) {
                $code = Hint::PARAM_ERROR;
                $msg = '用户未参与本局游戏';
                break;
            }
            //高度是否达到
            if($userStake['height'] <= $height) {
                $code = Hint::PARAM_ERROR;
                $msg = '当前高度已超过押注高度无法兑换';
                break;
            }

            //兑换过没有
            $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);
            $has = Redis::ZSCORE($allUserRewardKey, $userId);
            if(!empty($has)) {
                $code = Hint::ROOM_ROLE_INVITE_AGAIN;
                $msg = '已兑换';
                break;
            }

            $rewardPrice = round(($height*$userStake['basePrice'])/100);

            $log = [
                'game_num' => $gameNum,
                'user_id' => $userId,
                'height' => $userStake['height'],
                'r_height' => $height,
                'stakeCount' => $userStake['stakeCount'],
                'basePrice' => $userStake['basePrice'],
                'rewardPrice' => $rewardPrice,
                'status' => 1,
            ];

            //锁
            $ifLock = redis_lock($this->activityPromotionLockKey."REWARD:".$gameNum.'|'.$userId, 60);
            if(!$ifLock) {
                $code = Hint::SAME_TIME_NOT_REPEAT;
                break;
            }

            DB::beginTransaction();
            try{
                //加能量币
                $this->financeEnergyCoinModel->inc($userId, $gameNum, 1, $rewardPrice, '押注奖励');

                //更新
                $res = $this->angerbirdModel->updateLog($gameNum, $userId, ['status'=>1, 'r_height'=>$height, 'rewardPrice'=>$rewardPrice]);
                if(!$res) {
                    DB::rollBack();
                    $code = Hint::ERR_NORMAL;
                    $msg = '兑换失败';
                    break; 
                }

                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                write_log($this->errorLogName, 'ERROR 愤怒的小鸟用户兑换能量币失败', ['msg'=>$e->getMessage(), 'line'=>$e->getLine(), 'userId'=>$userId, 'game_num'=>$gameNum]);
                $code = Hint::ERR_NORMAL;
                $msg = '系统异常';
                break;
            }

            //用户押注信息
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            Redis::HSET($userStakeKey, $userId, json_encode($log));
            //某局兑换的所有用户
            $allUserRewardKey = $this->makeKey($this->allUserRewardKey, $gameNum);
            Redis::ZADD($allUserRewardKey, $now, $userId);
            Redis::expire($allUserRewardKey, $this->cacheExpire);
            //某局已兑换的能量币总值
            $allEnergyCoinRewardKey = $this->makeKey($this->allEnergyCoinRewardKey, $gameNum);
            Redis::INCRBY($allEnergyCoinRewardKey, $rewardPrice);
            Redis::expire($allEnergyCoinRewardKey, $this->cacheExpire);

            //游戏信息
            $this->angerBirdMsg(4, $gameNumNow, $userId);
        } while (false);

        //用户本局押注
        $data['user_stake_now'] = $this->angerbirdGetUserStake($userId, $gameNumNow, 1);
        //用户下一局押注
        $data['user_stake_next'] = $this->angerbirdGetUserStake($userId, ($gameNumNow+1), 1);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟本局押注用户列表
     */
    public function angerbirdUserList(){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            //获取配置
            $config = $this->angerbirdModel->getConfig();
            $config = array_column($config, 'value', 'key');
            //局数
            $gameNum = $this->_getGameNum();

            //押注用户
            $allUserStakeKey = $this->makeKey($this->allUserStakeKey, $gameNum);
            $userIds = Redis::zrevrange($allUserStakeKey, 0, 19);

            //用户信息
            $userList = $this->userModel->get_users_by_ids($userIds);
            $userList = array_column($userList, null, 'user_id');

            //用户押注
            $userStakeKey = $this->makeKey($this->userStakeKey, $gameNum);
            $stakeList = Redis::HGETALL($userStakeKey);

            $listEx = [];
            foreach($userIds as $userId) {
                if(empty($stakeList[$userId]) || empty($userList[$userId])) {
                    continue;
                }
                $stakeInfo = json_decode($stakeList[$userId], true);
                $stakeInfo['nickname'] = $userList[$userId]['nickname'];
                $stakeInfo['avatar'] = build_image($userList[$userId]['images'][0]);

                $listEx[] = $stakeInfo;
            }

            $data['list'] = $listEx;
        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟结果记录
     */
    public function angerbirdResList($limit=50){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            $list = $this->angerbirdModel->getGameStatList($limit);

            $listEx = [];
            foreach($list as $val) {
                $item = [];
                $item['id'] = $val['id'];
                $item['game_num'] = $val['gameNum'];
                $item['height'] = $val['winner'];
                $item['rewardPrice'] = $val['rewardPriceAll'];
                $item['created_at'] = $val['created_at'];

                $listEx[] = $item;
            }

            $data['list'] = $listEx;
        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 愤怒的小鸟用户飞行记录
     */
    public function angerbirdUserResList($userId, $page, $limit){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do {
            $listEx = [];
            $list = $this->angerbirdModel->userLogList($page, $limit, ['user_id'=>$userId]);
            if(!empty($list)) {
                foreach($list as $key=>$val) {

                    $item = [];
                    $item['id'] = $val['id'];
                    $item['game_num'] = $val['game_num'];
                    $item['user_id'] = $val['user_id'];
                    $item['height'] = $val['height'];
                    $item['r_height'] = $val['r_height'];
                    $item['basePrice'] = $val['basePrice'];
                    $item['rewardPrice'] = empty($val['status']) ? 0 : $val['rewardPrice'];
                    $item['status'] = $val['status'];
                    $listEx[] = $item;
                }
            }

            $data['list'] = $listEx;

        } while (false);

        return compact('code', 'msg', 'data');
    }

}